package org.checkboo.hopefullyengine.inversekinematics;

import java.util.LinkedList;

import org.checkboo.math.Matrix44f;
import org.checkboo.math.Quaternion;
import org.checkboo.math.Vector3f;

public class Bone {
	
	private int id;
	private String name;
	private Vector3f position;
	private Quaternion direction;
	private float length;
	
	private Vector3f localTranslation;
	private Quaternion localRotation;
	private Vector3f localScale;
	private Matrix44f totalTransform;
	private Matrix44f defaultTransform;
	private Matrix44f completeTransform;
	private Matrix44f localTransform;
	private LinkedList<Bone> children;
	
	public Bone(int id,String name){
		this.id = id;
		this.name = name;
		this.children = new LinkedList<Bone>();
		this.totalTransform = new Matrix44f();
		this.totalTransform.identity();
		this.localTranslation = new Vector3f();
		this.localRotation = new Quaternion();
		this.localRotation.setIdentity();
		this.localScale = new Vector3f(1.0f, 1.0f, 1.0f);
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Vector3f getPosition() {
		return position;
	}

	public void setPosition(Vector3f position) {
		this.position = position;
	}

	public Quaternion getDirection() {
		return direction;
	}

	public void setDirection(Quaternion direction) {
		this.direction = direction;
	}

	public float getLength() {
		return length;
	}

	public void setLength(float length) {
		this.length = length;
	}

	public Vector3f getLocalTranslation() {
		return localTranslation;
	}

	public void setLocalTranslation(Vector3f localTranslation) {
		this.localTranslation = localTranslation;
	}

	public Quaternion getLocalRotation() {
		return localRotation;
	}
	public void setLocalRotation(Quaternion localRotation) {
		this.localRotation = localRotation;
	}
	public Vector3f getLocalScale() {
		return localScale;
	}
	public void setLocalScale(Vector3f localScale) {
		this.localScale = localScale;
	}
	public Matrix44f getTotalTransform() {
		if(null == this.totalTransform){
			this.totalTransform = new Matrix44f();
			this.totalTransform.identity();
		}
		return totalTransform;
	}
	
	public Matrix44f getCompleteTransform(){
		if(null == this.completeTransform){
			this.completeTransform = new Matrix44f();
			this.completeTransform.identity();
		}
		return this.completeTransform;
	}
	
	public Matrix44f getDefaultTransform(){
		if(null == this.defaultTransform){
			this.defaultTransform = new Matrix44f();
			this.defaultTransform.identity();
			this.defaultTransform.rotate(this.direction.toRotationMatrix());
			this.defaultTransform.translate(new Vector3f(length, 0.0f, 0.0f));
		}
		return this.defaultTransform;
	}
	
	public void setDefaultTransform(Matrix44f transform){
		this.defaultTransform = transform;
	}
	
	public Matrix44f getDefaultTransformInverse(){
		return (new Matrix44f(getDefaultTransform())).inverse();
	}
	
	public void setTotalTransform(Matrix44f totalTransform) {
		//totalTransform.multiply(getDefaultTransform());
		this.totalTransform.set(totalTransform);
	}
	public Matrix44f getLocalTransform(){
		if(null == this.localTransform)
			this.localTransform = new Matrix44f();
		this.localTransform.identity();
		this.localTransform.rotate(this.localRotation.toRotationMatrix());
		this.localTransform.translate(this.localTranslation);
		return (new Matrix44f(getDefaultTransform()).multiply(this.localTransform));
	}
	public LinkedList<Bone> getChildren() {
		return children;
	}
	public void setChildren(LinkedList<Bone> children) {
		this.children = children;
	}
	public void addChild(Bone child){
		if(null == this.children)
			this.children = new LinkedList<Bone>();
		this.children.add(child);
	}
	public void reset(){
		this.localTranslation.zero();
		this.localRotation.setIdentity();
		this.localScale.set(1.0f, 1.0f, 1.0f);
	}
}
